package info.hexin.ioc.context.impl;

import info.hexin.ioc.IocBean;
import info.hexin.ioc.annotation.Scope;
import info.hexin.ioc.context.Ioc;
import info.hexin.ioc.loader.Loader;
import info.hexin.lang.Exceptions;
import info.hexin.lang.Strings;

import java.util.Map;

/**
 * 统一抽象context加载
 * 
 * @author hexin
 * 
 */
public class SimpleIoc implements Ioc {

    protected Map<String, IocBean> beans;

    public SimpleIoc(Loader resourceLoader) {
        beans = resourceLoader.getBeans();
    }

    @Override
    public Object getBean(String beanName) {
        if (containsBean(beanName)) {
            IocBean iocBean = beans.get(beanName);
            if (iocBean.isSingleton()) {
                return iocBean.getInstance();
            } else {
                return iocBean.newInstance();
            }
        } else {
            throw Exceptions.make("beanName >>> " + beanName + "  没有找到!!");
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T getBean(Class<T> clazz) {
        String className = clazz.getSimpleName();
        String name = Strings.lowerFirst(className);
        IocBean iocBean = beans.get(name);

        if (iocBean == null) {
            for (Map.Entry<String, IocBean> entry : beans.entrySet()) {
                IocBean tmpIocBean = entry.getValue();
                Object object = tmpIocBean.getInstance();
                if (clazz.isInstance(object)) {
                    iocBean = tmpIocBean;
                }
            }
        }

        if (iocBean == null) {
            throw Exceptions.make("clazz >>> " + clazz + "  没有找到!!");
        }

        if (iocBean.isSingleton()) {
            return (T) iocBean.getInstance();
        } else {
            return (T) iocBean.newInstance();
        }
    }

    @Override
    public boolean containsBean(String name) {
        return beans.containsKey(name);
    }

    @Override
    public boolean isSingleton(String name) {
        ensureContains(name);
        IocBean bean = beans.get(name);
        return Scope.singleton == bean.getScope();
    }

    @Override
    public void load(Ioc parent) {
        if (parent == null) {
            return;
        }
        this.beans.putAll(parent.getIocBeans());
    }

    @Override
    public Map<String, IocBean> getIocBeans() {
        return beans;
    }

    /**
     * 没有找到，抛出异常
     * 
     * @param beanName
     */
    private void ensureContains(String beanName) {
        if (!containsBean(beanName)) {
            throw Exceptions.make("beanName >>> " + beanName + "  没有找到!!");
        }
    }
}
